package db

import (
	"context"
	"fmt"
	"svr/src/logs"
	"svr/src/xutil"
	"time"

	"github.com/go-redis/redis/v8"
)

var rds *redis.Client

func createRedis() *redis.Client {
	rds := redis.NewClient(&redis.Options{
		Addr: "127.0.0.1:6379",
		// Password: "qqqq1111",
		DB: 1,
	})
	err := rds.Set(GetCtx(), "init", time.Now(), 0).Err()
	if xutil.CheckErr(err) {
		return nil
	}
	return rds
}

func InitRedis() *redis.Client {
	rds = createRedis()
	return rds
}

func GetRedis() *redis.Client {
	if rds == nil {
		return createRedis()
	}
	return rds
}

func GetRedisKey(vals ...interface{}) string {
	k := ""
	for _, v := range vals {
		if k == "" {
			k = fmt.Sprintf("%v", v)
		} else {
			k = fmt.Sprintf("%v:%v", k, v)
		}
	}
	return k
}

type DbLock struct {
	Key      string
	Password string
	LockKey  string
}

func LockKeys(vals ...interface{}) *DbLock {
	return LockKey(GetRedisKey(vals))
}
func LockKey(k string) *DbLock {
	// if conf.ServerConfig.ServerType == msg.DeviceType_SingleLogic {
	// 	return lockKeySingleLogic(k)
	// }
	lockKey := k + ":lock"
	rds := GetRedis()
	pw := xutil.GetRandomIntString()
	v := false
	var err error
	ct := time.Duration(0)
	for !v {
		v, err = rds.SetNX(GetCtx(), lockKey, pw, time.Second).Result()
		if err != nil {
			logs.Errorf("redis:LockKey error link")
			return nil
		}
		if v {
			break
		}
		ct++
		if ct > 20 {
			logs.Errorf("redis:LockKey error locked, key:%v", k)
			return nil
		}
		time.Sleep(time.Millisecond * (20 + ct))
	}
	return &DbLock{
		Key:      k,
		LockKey:  lockKey,
		Password: pw,
	}
}

func UnlockKey(dl *DbLock) {
	// if conf.ServerConfig.ServerType == msg.DeviceType_SingleLogic {
	// 	UnlockKeySingleLogic(k, pw)
	// 	return
	// }
	if dl != nil {
		rds := GetRedis()
		v, err := rds.Get(GetCtx(), dl.LockKey).Result()
		if err == nil && v == dl.Password {
			rds.Del(GetCtx(), dl.LockKey)
		}
	}
}

func GetCtx() context.Context {
	return context.Background()
}

// var mapLockKeys *xutil.Map

func lockKeySingleLogic(k string) (string, string, error) {
	// if mapLockKeys == nil {
	// 	mapLockKeys = xutil.CreateMap()
	// }
	// pw := xutil.GetRandomIntString()
	// v := true
	// var err error
	// ct := time.Duration(0)
	// for v {
	// 	v = mapLockKeys.ContainsKey(k)
	// 	if !v {
	// 		break
	// 	}
	// 	time.Sleep(time.Millisecond * (20 + ct))
	// 	ct++
	// 	if ct > 20 {
	// 		return "", "", fmt.Errorf("redis:LockKey error locked, key:%v", k)
	// 	}
	// 	time.Sleep(time.Millisecond * (20 + ct))
	// }
	// return k, pw, nil
	return "", "", nil
}
func UnlockKeySingleLogic(k, pw string) {

}
